package server.world.character

import server.world._
import server.world.action._
import server.world.item._
import server.world.map._

class GameCharacter(var tile:Tile) extends MapObject{
			
      var PStats:Map[String,Float] = Map("STR" -> 10, "DEX" -> 10, "INT" -> 10)
      var backpack:List[Item] = List()
      var skillbook:SkillBook = new SkillBook()
      var inv:Inventory =  Inventory()
      
			tile.characterOnTile = this
			name = "a character"
      
      var actionPending = false
      var attackdisabled = 0f
      
//########################### Primary Stat related code ###############################################
			var hp = 0f
			var mana = 0f
      
			def updatePstat(stat:String,num:Int) = PStats(stat) -> num
			
			var rand = new scala.util.Random
			def tapR(f: =>Float):Float = f *(0.5f + (rand.nextFloat/2f))
			
//############# Functions used to generate secondary stats ########################### 
			
			//HP, Mana and their regenaration
			def getMaxHP():Float= 10*PStats("STR")
			def getHpRegen():Float= (1/10)*PStats("STR")
			def getMaxMana():Float = 10*PStats("INT")
			def getManaReg():Float = (1/10)*PStats("INT")
			
			//Armour Stuff
			def getAC():Float = PStats("DEX") + inv.getAC //damge reduction vs phys dmg
			def getEV():Float = PStats("DEX") + inv.getEV //Chance to evade incoming attacks of all types
			//def getSH():Float = inv.getSlot(2).asInstanceOf[Shield].SH //chance to block with shield
			
			//Weapon Stuff	
			def getBaseDamage():Float = PStats("STR")+(1/2)*PStats("DEX") + inv.getSlotStat[Weapon](inv.Hand1, Weapon => Weapon.damage)
			def getCritC():Float = (1/10)*PStats("DEX") + inv.getSlotStat[Weapon](inv.Hand1, Weapon => Weapon.critC)
			def getCritM():Float= PStats("DEX") + inv.getSlotStat[Weapon](inv.Hand1, Weapon => Weapon.critM)
			
			def getAcc():Float = 10*PStats("DEX") + inv.getSlotStat[Weapon](inv.Hand1, Weapon => Weapon.acc) //Acuracy for landing melee and ranged attacks paired vs EV
			def getDamage():Float = if(rand.nextFloat >= getCritC/100) tapR(getBaseDamage)*getCritM else tapR(getBaseDamage)
			
			//Magic Related
			def getSpellPower():Float= 10*PStats("INT") //spell power, determanes the effectivness of the spells 
			
			
			//AP related
			def apmod():Float = (1/100)*PStats("DEX").toFloat + 0.9.toFloat
			
			def attackAP():Float = (3 + inv.getSlotStat[Weapon](inv.Hand1, Weapon => Weapon.apcost))/apmod()
			def moveAP():Float = 5f/apmod
			
			//Weight Related
			def getWeightTollarance():Float = 10*PStats("STR")
			
			def BackpackWeight():Float = {
			  var weight = 0f
			  for(item <- backpack){ 
			    weight = weight + item.weight
			}
			  return weight
			}
			
			def WeightAPmod():Float = if(BackpackWeight < getWeightTollarance) 0 else  BackpackWeight/getWeightTollarance
			
///############################

			def spawn(){ //invoked to crate living char
				hp = getMaxHP()
				mana = getMaxMana()
			}
			
			def isAlive():Boolean = hp>0

			
			def reciveDMG(dmg:Float) {
			  hp = hp - dmg
			}
			
			def spendMana(manacost:Int){
			  mana = mana - manacost
			}
			
			def visibleTiles():List[Tile] = {
			  var visloc:List[Tile] = List()
			  for(x <- -6 to 6)
			    for(y <- -12 to 12){
            if(tile.map.tileExists(tile.xCor + x, tile.yCor +y)){
                visloc = tile.map.getTile(tile.xCor + x, tile.yCor +y) :: visloc
            }
			    }
			  return visloc
			}	
			
			def isabletoFire() = inv.Hand1.getOrElse(false).isInstanceOf[RangedWeapon] & !inv.Quiver.isEmpty
      def isabletoAct() = !actionPending & (attackdisabled <= 0)
         
}
